using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Xml;
using SemWeb;
using SemWeb.Inference;
using SemWeb.Query;

namespace SimpleStateMachine
{
    internal class Program
    {
        private static readonly string ontologyLocation =
            @"C:\dev\prototypes\semantic-web\ontologies\2007\04\states\";

        private static string baseUri = @"file:///C:/dev/prototypes/semantic-web/ontologies/2007/04/states/states.rdf#";
        private static MemoryStore store = new MemoryStore();
        private static Entity Machine1 = new Entity(baseUri + "Machine1");
        private static Entity Input1 = new Entity(baseUri + "I1");
        private static Entity Input2 = new Entity(baseUri + "I2");
        private static Entity theSystem = new Entity(baseUri + "This");
        private static string hasInput = baseUri + "hasInput";
        private static string isInState = baseUri + "isInState";

        private static void Main(string[] args)
        {
            InitialiseStore();
            DisplayCurrentStates();
            SetNewInput(Input2);
            DisplayCurrentStates();
        }

        private static void DisplayCurrentStates()
        {
            SelectResult ra = store.Select(new Statement(Machine1, new Entity(isInState), null));
            Debug.Write("Current states: ");
            foreach (Statement resource in ra.ToArray())
            {
                Debug.Write(resource.Object.Uri);
            }
            Debug.WriteLine("");
        }

        private static void InitialiseStore()
        {
            string statesLocation = Path.Combine(ontologyLocation, "states.n3");
            string statesLocation2 = Path.Combine(ontologyLocation, "states.rdf");
            string rulesLocation = Path.Combine(ontologyLocation, "rules.n3");
            Euler engine = new Euler(new N3Reader(File.OpenText(rulesLocation)));
            store.Import(new N3Reader(File.OpenText(statesLocation)));
            store.AddReasoner(engine);
        }

        private static void SetNewInput(Entity newInput)
        {
            Resource[] currentInput = store.SelectObjects(theSystem, hasInput);
            Statement input = new Statement(theSystem, hasInput, Input1);
            store.Remove(new Statement(theSystem, hasInput, currentInput[0]));
            store.Add(new Statement(theSystem, hasInput, newInput));
            Resource[] subsequentState = store.SelectObjects(Machine1, isInState);
            Statement newState = new Statement(Machine1, isInState, subsequentState[0]);
            store.Replace(new Statement(Machine1, isInState, null), newState);
        }
    }
}